package com.cc.dao;

import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * @author lenovo
 * @version 1.0
 * @description: 数据库连接类
 * @date 2025/2/21 9:51
 */
public class BaseDao {
    private static final Logger logger = Logger.getLogger(BaseDao.class);
    //驱动
    private static String DRIVER = null;
    //数据库连接地址
    private static String URL = null;
    //用户名
    private static String USER = null;
    //密码
    private static String PWD = null;
    //数据库连接对象
    Connection conn = null;
    //指令操作对象
    PreparedStatement pstmt = null;
    //结果集
    ResultSet rs = null;

    //静态代码块
    static {
        String configFile = "database.properties";
        /**
         * 通过类加载器获取指定配置文件的输入流。
         * 该方法使用当前类的类加载器来加载资源文件，并返回一个输入流以便读取文件内容。
         *
         * @param configFile 配置文件的路径，相对于类路径的根目录。
         * @return InputStream 返回一个输入流，用于读取配置文件的内容。如果文件不存在，则返回null。
         */
        InputStream is = BaseDao.class.getClassLoader().getResourceAsStream(configFile);
        Properties properties = new Properties();
        try {
            //读取配置文件信息
            properties.load(is);
            DRIVER = properties.getProperty("driver");
            URL = properties.getProperty("url");
            USER = properties.getProperty("username");
            PWD = properties.getProperty("password");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //加载驱动
        try {
            Class.forName(DRIVER);
            logger.debug("驱动加载成功！");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取数据库连接。
     * 该方法通过JDBC的DriverManager获取数据库连接，并返回该连接对象。
     * 如果连接成功，会在日志中记录调试信息；如果连接失败，会打印异常堆栈信息。
     *
     * @return Connection 返回一个数据库连接对象，如果连接失败则返回null。
     */
    public Connection getConnection() {
        try {
            // 通过DriverManager获取数据库连接
            conn = DriverManager.getConnection(URL, USER, PWD);
            // 记录数据库连接成功的调试信息
            logger.debug("数据库连接成功！");
        } catch (Exception e) {
            // 捕获并打印连接过程中可能出现的异常
            e.printStackTrace();
        }
        return conn;
    }
    //关闭连接
    public void closedAll(ResultSet rs){
        try {
            if(rs!=null){
                rs.close();
            }
            if(pstmt!=null){
                pstmt.close();
            }
            if (conn!=null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        logger.debug("连接关闭成功");
    }
//执行增删除方法

    /**
     * 执行数据库的增、删、改操作。
     *
     * @param sql    要执行的SQL语句，通常为INSERT、UPDATE或DELETE语句。
     * @param params SQL语句中的参数，可以为空。
     * @return 返回受影响的行数。如果执行失败，返回-1。
     */
    public int executeUpdate(String sql, Object... params) {
        // 打开数据库连接
        conn = getConnection();
        try {
            // 记录执行的SQL语句，便于调试
            logger.debug("增删改操作指令：" + sql);

            // 预编译SQL语句
            pstmt = conn.prepareStatement(sql);

            // 如果参数不为空，设置SQL语句中的参数
            if (null != params) {
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }
            }

            // 执行SQL语句并返回受影响的行数
            return pstmt.executeUpdate();
        } catch (SQLException e) {
            // 捕获并打印SQL异常
            e.printStackTrace();
        } finally {
            // 关闭数据库连接和相关资源
            closedAll(null);
        }
        // 如果执行失败，返回-1
        return -1;
    }
    //执行查询方法
    public ResultSet executeQuery (String sql, Object...params){
        //打开连接
        conn = getConnection();
        try {
            logger.debug("执行查询指令：" + sql);
            //创建指令
            pstmt = conn.prepareStatement(sql);
            if (null != params) {
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            rs = pstmt.executeQuery();
            return rs;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
